home *** CD-ROM | disk | FTP | other *** search
/ boe.pres.k12.wv.us / boe.pres.k12.wv.us.zip / boe.pres.k12.wv.us / Utilities / Xerox Workcentre 5335 / Windows Scan / 64-bit_x64 / Russian / cpsimage.cab / data / xps / XpsPackagingStrategy.elf < prev    next >
Text File  |  2009-04-23  |  64KB  |  1,601 lines

  1. /*****************************************************************************/
  2. /*
  3. ** This script contains a set of classes for writing an XPS package to file.
  4. ** The classes provide the means to organize the parts of an XPS package in
  5. ** one of four interleaving orders: NONE; RESOURCES FIRST; RESOURCES LAST;
  6. ** and IMAGES LAST.
  7. **
  8. ** A concrete instance of a packaging strategy is created using the
  9. ** XpsPackagingStrategyFactory class. The getStrategy method of this class
  10. ** is used to obtain the packaging strategy instance.
  11. */
  12. /*****************************************************************************/
  13.  
  14. #load "sys/datetime.elf";
  15. #load "sys/lang.elf";
  16. #load "sys/stdio.elf";
  17. #load "sys/transform2d.elf";
  18. #load "sys/xipxml.elf";
  19. #load "sys/XmlWriter.elf";
  20. #load "xipProcs/xipflatten.proc";
  21. #load "xps/Xps.elf";
  22. #load "xps/XpsPackage.elf";
  23. #load "xps/XpsSequence.elf";
  24. #load "xps/XpsDocument.elf";
  25. #load "xps/XpsPage.elf";
  26. #load "xps/XpsResource.elf";
  27.  
  28.  
  29. /****************************************************************************/
  30. PROCEDURE XpsDSigMakeSignature (STRING rootPath, LIST options)
  31.   RETURNS (STRING doc) NATIVE "XPSDSigMakeSignature@documentio";
  32.  
  33. /****************************************************************************/
  34. /*
  35. ** This class defines the write method for a non-standard core property of an
  36. ** XPS package.
  37. */
  38. /* @write Writes a non-standard core property of an XPS package. */
  39. /****************************************************************************/
  40. private CLASS GenericPropertyWriter {
  41.    METHOD write (XmlWriter writer, STRING name, STRING value) {
  42.       writer.writeElementString (localName: name, text: value);
  43.    }
  44. }  
  45.  
  46. /****************************************************************************/
  47. /*
  48. ** This class defines the write method for a date-time core property of an
  49. ** XPS package.
  50. */
  51. /* @write Writes a date-time core property of an XPS package. */
  52. /****************************************************************************/
  53. private CLASS DateTimePropertyWriter { 
  54.    METHOD write (XmlWriter writer, STRING name, STRING value) {
  55.       writer.writeElementStart (prefix: "dcterms", localName: name);
  56.       writer.writeAttributeString (prefix: "xsi", localName: "type",
  57.          text: "dcterms:W3CDTF", ns: Xps.XSI_NAMESPACE);
  58.       writer.writeString (text: value);
  59.       writer.writeElementEnd ();
  60.    }
  61. }  
  62.  
  63. /****************************************************************************/
  64. /*
  65. ** This class defines the write method for a text core property of an
  66. ** XPS package.
  67. */
  68. /* @write Writes a text core property of an XPS package. */
  69. /****************************************************************************/
  70. private CLASS StringPropertyWriter {
  71.    METHOD write (XmlWriter writer, STRING name, STRING value) {
  72.       writer.writeElementString (prefix: "dc", localName: name, text: value);
  73.    }
  74. }
  75.  
  76. /****************************************************************************/
  77. /*
  78. ** This class represents the location of a digital signature spot.
  79. */
  80. /****************************************************************************/
  81. CLASS XpsSpotLocation {
  82.    // Fields
  83.    STRING pageUri;
  84.    DOUBLE xpos;
  85.    DOUBLE ypos;
  86.  
  87.    METHOD toArgList () RETURNS (LIST lst) {
  88.       lst.insert (name: "pageUri", obj: this.pageUri);
  89.       lst.insert (name: "xpos",    obj: this.xpos);
  90.       lst.insert (name: "ypos",    obj: this.ypos);
  91.    }
  92. }
  93.  
  94. /****************************************************************************/
  95. /*
  96. ** This class represents a digital signature request.
  97. */
  98. /****************************************************************************/
  99. CLASS XpsDSigRequest {
  100.    // Fields
  101.    STRING          signerName;
  102.    STRING          intent;
  103.    STRING          signingLocale;
  104.    DATETIME        signBy;
  105.    XpsSpotLocation spotLocation;
  106.  
  107.    METHOD toArgList () RETURNS (LIST lst) {
  108.       if (this.signerName)
  109.          lst.insert (name: "signerName", obj: this.signerName);
  110.  
  111.       if (this.intent)
  112.          lst.insert (name: "intent", obj: this.intent);
  113.  
  114.       if (this.signingLocale)
  115.          lst.insert (name: "signingLocale", obj: this.signingLocale);
  116.  
  117.       if (this.signBy) {
  118.          DATETIME dt = this.signBy.toUTC ();
  119.          lst.insert (name: "signBy",
  120.             obj: dt.toString (format: DATETIME.W3CZ_FORMAT));
  121.          }
  122.  
  123.       if (this.spotLocation)
  124.          lst.insert (name: "spotLocation",
  125.             obj: this.spotLocation.toArgList ());
  126.    }
  127. }
  128.  
  129. /****************************************************************************/
  130. /*
  131. ** This class defines the options for XPS packaging strategy instances.
  132. */
  133. /****************************************************************************/
  134. CLASS XpsOptions {
  135.    /* Secure writing indicator */
  136.    BOOLEAN         security = TRUE;
  137.  
  138.    /* Timestamp indicator */
  139.    BOOLEAN         noTimestamp = FALSE;
  140.  
  141.    /* Filename for X509 certificate (PKCS12 format) */
  142.    STRING          certFile;
  143.  
  144.    /* Password for private key of X509 certificate */
  145.    STRING          certPassword;
  146.  
  147.    /* Intention agreement that signer signs against */
  148.    STRING          intent;
  149.  
  150.    /* Legal jurisdiction where package is signed */
  151.    STRING          signingLocale;
  152.  
  153.    /* Location to display visual digital signature spot */
  154.    XpsSpotLocation spotLocation;
  155.  
  156.    /* List of digital signature requests */
  157.    LIST            requests;
  158. }
  159.  
  160. /****************************************************************************/
  161. /*
  162. ** This class defines the abstract base class for XPS packaging strategy
  163. ** classes.
  164. */
  165. /* @addLayersContent Writes XML content for image layers of fixed page. */
  166. /* @close Removes the temporary archive build directory and closes the zip archive. */
  167. /* @color2hex Converts an XIPCOLOR object to a hexadecimal value. */
  168. /* @makeDocRelsUri Creates a URI for fixed document relationships part. */
  169. /* @makeDocUri Creates a URI for a fixed document part. */
  170. /* @makePageRelsUri Creates a URI for a fixed page relationships part. */
  171. /* @makePageUri Creates a URI for a fixed page part. */
  172. /* @makePathDataValue Creates geometric description of the area for an image. */
  173. /* @makeViewboxValue Creates viewbox description for an image. */
  174. /* @makeViewboxValue Creates viewport description for an image. */
  175. /* @mapHex Converts an integer value to hexadecimal. */
  176. /* @open Creates a zip archive and a temporary archive build directory for an XPS package. */
  177. /* @write Writes a XPS package. [abstract] */
  178. /* @writeCoreProperties Writes XML file for core properties. */
  179. /* @writeDigitalSignature Writes files for digital signature. */
  180. /* @writeDocumentReference Writes XML element for document reference. */
  181. /* @writeEmptyPrintTicket Writes XML file for empty print ticket. */
  182. /* @writeExtType Writes XML element for file extension content type. */
  183. /* @writeFixedPage Writes XML file for fixed page. */
  184. /* @writePageContent Writes XML element for page content. */
  185. /* @writePartEnd Writes end tag for open XML element of a package part. */
  186. /* @writePartRel Writes XML element for package part relationship. */
  187. /* @writePartStart Writes the xml declaration and the specified XML element start tag for a package part. */
  188. /* @writePartType Writes XML element for package part content type. */
  189. /****************************************************************************/
  190. CLASS XpsBasePackagingStrategy {
  191.    // Fields
  192.    STRING     name;
  193.    ZIP        zip;
  194.    FILE       rootDir;
  195.    STRING     rootPath;
  196.    XmlWriter  typesWriter;
  197.    INTEGER    typesCount;
  198.    XmlWriter  relsWriter;
  199.    INTEGER    relsCount;
  200.    XmlWriter  seqRelsWriter;
  201.    XmlWriter  propsWriter;
  202.    XmlWriter  seqWriter;
  203.    INTEGER    seqCount;
  204.    XmlWriter  docWriter;
  205.    XmlWriter  docRelsWriter;
  206.    XmlWriter  pageWriter;
  207.    XmlWriter  pageRelsWriter;
  208.    XmlWriter  ptWriter;
  209.    LIST       propWriterMap;
  210.  
  211.    BOOLEAN    doIndent    = FALSE;
  212.    BOOLEAN    signPackage = FALSE;
  213.    XpsOptions options;
  214.  
  215.    METHOD write (XpsPackage pkg, STRING filename, XpsOptions options) {
  216.    }
  217.  
  218.    // Protected Methods
  219.    METHOD open (STRING filename, XpsOptions options) {
  220.       if (options.certFile) {
  221.          if (!options.certPassword) {
  222.             SetStatus(op: "stop",
  223.                 msg:"InvalidArgumentException: " +
  224.                     "Missing password for certificate file");
  225.             }
  226.  
  227.          if (!this.name.strcasecmp (str: "XpsNoInterleavingStrategy")) {
  228.             SetStatus (op: "stop",
  229.                 msg:"UnsupportedException: " +
  230.                     "Cannot digitally sign XPS interleaved package");
  231.             }
  232.  
  233.          this.signPackage = TRUE;
  234.          }
  235.  
  236.       if (!filename)
  237.          filename = Xps.DEFAULT_PKG_FILENAME;
  238.  
  239.       if (!filename.ext ().strcasecmp (str: "xps"))
  240.          filename += ".xps";
  241.  
  242.       FILE outfile  = new (FILE, path: filename);
  243.       if (outfile.exists ())
  244.          outfile.deleteFile ();
  245.       this.zip = new (ZIP, file: outfile);
  246.       this.zip.setOption (option: ZIP.NODIRS);
  247.       if (options.noTimestamp)
  248.          this.zip.setOption (option: ZIP.NOTIME);
  249.  
  250.       this.rootDir  = FILE.createTempDirectory (name: outfile.getName ());
  251.       this.rootPath = this.rootDir.getAbsolutePath ();
  252.       this.options  = options;
  253.    }
  254.  
  255.    METHOD close () {
  256.       if (!this.options.security && this.rootDir && this.rootDir.exists ()) {
  257.          this.rootDir.deleteFiles (recurse: TRUE);
  258.          }
  259.  
  260.       if (this.zip)
  261.          this.zip.close ();
  262.    }
  263.  
  264.    METHOD writePartStart (XmlWriter writer, STRING prefix, STRING localName,
  265.                           STRING ns) {
  266.       writer.writeDocumentStart ();
  267.       writer.writeElementStart (prefix: prefix, localName: localName, ns: ns);
  268.    }
  269.  
  270.    METHOD writePartEnd (XmlWriter writer) {
  271.       writer.writeElementEnd ();
  272.       writer.writeDocumentEnd ();
  273.       writer.flush ();
  274.    }
  275.  
  276.    METHOD writeExtType (STRING ext, STRING type) {
  277.       this.typesWriter.writeElementStart (localName: "Default");
  278.       this.typesWriter.writeAttributeString (localName: "Extension",
  279.          text: ext);
  280.       this.typesWriter.writeAttributeString (localName: "ContentType",
  281.          text: type);
  282.       this.typesWriter.writeElementEnd ();
  283.    }
  284.  
  285.    METHOD writePartType (STRING partName, STRING type) {
  286.       this.typesWriter.writeElementStart (localName: "Override");
  287.       this.typesWriter.writeAttributeString (localName: "PartName",
  288.          text: partName);
  289.       this.typesWriter.writeAttributeString (localName: "ContentType",
  290.          text: type);
  291.       this.typesWriter.writeElementEnd ();
  292.    }
  293.  
  294.    METHOD writePartRel (XmlWriter writer, STRING target, STRING id,
  295.                         STRING type) {
  296.       writer.writeElementStart (localName: "Relationship");
  297.       writer.writeAttributeString (localName: "Target", text: target);
  298.       writer.writeAttributeString (localName: "Id",     text: id);
  299.       writer.writeAttributeString (localName: "Type",   text: type);
  300.       writer.writeElementEnd ();
  301.    }
  302.  
  303.    METHOD writeDocumentReference (INTEGER docNum) {
  304.       this.seqWriter.writeElementStart (localName: "DocumentReference");
  305.       this.seqWriter.writeAttributeString (localName: "Source",
  306.          text: this.makeDocUri (docNum: docNum));
  307.       this.seqWriter.writeElementEnd ();
  308.    }
  309.  
  310.    METHOD writePageContent (INTEGER docNum, INTEGER pgNum) {
  311.       this.docWriter.writeElementStart (localName: "PageContent");
  312.       this.docWriter.writeAttributeString (localName: "Source",
  313.          text: this.makePageUri (docNum: docNum, pgNum: pgNum));
  314.       this.docWriter.writeElementEnd (); 
  315.    }
  316.  
  317.    METHOD writeCoreProperties (XpsCoreProperties props) {
  318.       this.propsWriter = XmlWriterFactory.createFileWriter (
  319.                             filename: this.rootPath + Xps.CORE_PROPS_PATH,
  320.                               indent: this.doIndent
  321.                             );
  322.  
  323.       this.writePartStart (writer: this.propsWriter,
  324.          localName: "coreProperties");
  325.  
  326.       this.propsWriter.writeAttributeString (prefix: "xmlns", localName: "dc",
  327.          text: Xps.DC_ELEMS_NAMESPACE);
  328.       this.propsWriter.writeAttributeString (prefix: "xmlns",
  329.          localName: "dcterms", text: Xps.DC_TERMS_NAMESPACE);
  330.       this.propsWriter.writeAttributeString (localName: "xmlns",
  331.          text: Xps.CORE_PROPS_NAMESPACE);
  332.       this.propsWriter.writeAttributeString (prefix: "xmlns", localName: "xsi",
  333.          text: Xps.XSI_NAMESPACE);
  334.  
  335.       if (this.propWriterMap.length () == 0) {
  336.          this.propWriterMap.insert (name: "title",
  337.             obj: new (StringPropertyWriter));
  338.          this.propWriterMap.insert (name: "subject",
  339.             obj: new (StringPropertyWriter));
  340.          this.propWriterMap.insert (name: "creator",
  341.             obj: new (StringPropertyWriter));
  342.          this.propWriterMap.insert (name: "created",
  343.             obj: new (DateTimePropertyWriter));
  344.          this.propWriterMap.insert (name: "modified",
  345.            obj: new (DateTimePropertyWriter));
  346.          this.propWriterMap.insert (name: "keywords",
  347.            obj: new (GenericPropertyWriter));
  348.          }
  349.  
  350.       STRING value;
  351.       LIST propNames = props.propertyNames ();
  352.       foreach (propNames : name) {
  353.          value = props.getProperty (name: name);
  354.  
  355.          this.propWriterMap.ref (name: name
  356.             ).write (writer: this.propsWriter, name: name, value: value
  357.             );
  358.          }
  359.  
  360.       this.writePartEnd (writer: this.propsWriter);
  361.    }
  362.  
  363.    METHOD writeDigitalSignature (XpsPackage pkg) {
  364.       /* Write digital signature origin part */
  365.       STRING dsigPath = this.rootPath + Xps.DSIG_PATH;
  366.       new (FILE, path: dsigPath).mkdirs ();
  367.  
  368.       STRING emptyContent = "";
  369.       emptyContent.Write (filename: dsigPath + "/origin.psdsor", value: 1);
  370.       this.zip.addFile (dir: this.rootDir,
  371.          file: new (FILE, path: dsigPath + "/origin.psdsor"));
  372.  
  373.       /* Write digital signature origin part rels */
  374.       STRING dsigRelsPath = dsigPath + Xps.RELS_PATH;
  375.       new (FILE, path: dsigRelsPath).mkdirs ();
  376.  
  377.       XmlWriter writer = XmlWriterFactory.createFileWriter (
  378.                             filename: dsigRelsPath + "/origin.psdsor.rels",
  379.                             indent: this.doIndent);
  380.       this.writePartStart (writer: writer,
  381.          localName: "Relationships", ns: Xps.RELS_NAMESPACE);
  382.       this.writePartRel (writer: writer,
  383.          target: Xps.DSIG_XML_PATH + "/signature.psdsxs",
  384.          id: "RelsSignature0", type: Xps.RELS_DIGITAL_SIGNATURE_URI);
  385.       this.writePartEnd (writer: writer);
  386.       this.zip.addFile (dir: this.rootDir,
  387.          file: new (FILE, path: dsigRelsPath + "/origin.psdsor.rels"));
  388.  
  389.       STRING defPath = this.rootPath + "/xmls";
  390.       new (FILE, path: defPath).mkdirs ();
  391.  
  392.       STRING xmlDsigPath = this.rootPath + Xps.DSIG_XML_PATH;
  393.       new (FILE, path: xmlDsigPath).mkdirs ();
  394.  
  395.       STRING certPath = this.rootPath + Xps.DSIG_CERT_PATH;
  396.       new (FILE, path: certPath).mkdirs ();
  397.  
  398.       LIST dsigOpts;
  399.       dsigOpts.insert (name: "certFile",      obj: this.options.certFile);
  400.       dsigOpts.insert (name: "certPassword",  obj: this.options.certPassword);
  401.       dsigOpts.insert (name: "intent",        obj: this.options.intent);
  402.       dsigOpts.insert (name: "signingLocale", obj: this.options.signingLocale);
  403.       dsigOpts.insert (name: "noTimestamp",   obj: this.options.noTimestamp);
  404.  
  405.       if (this.options.spotLocation) {
  406.          XpsSpotLocation spot = this.options.spotLocation;
  407.          dsigOpts.insert (name: "spotLocation", obj: spot.toArgList ());
  408.          }
  409.  
  410.       if (this.options.requests.length () > 0) {
  411.          XpsDSigRequest req;
  412.          LIST           lst;
  413.          INTEGER        i;
  414.  
  415.          for (i = 0; i < this.options.requests.length (); i++) {
  416.             req = this.options.requests[i];
  417.             lst.insert (entry: i, obj: req.toArgList ());
  418.             }
  419.          dsigOpts.insert (name: "requests", obj: lst);
  420.          }
  421.  
  422.       STRING dsig = XpsDSigMakeSignature (
  423.                        rootPath: this.rootPath,
  424.                         options: dsigOpts
  425.                        );
  426.       dsig.Write (filename: xmlDsigPath + "/signature.psdsxs", value: 1);
  427.       this.zip.addFile (dir: this.rootDir,
  428.          file: new (FILE, path: xmlDsigPath + "/signature.psdsxs"));
  429.  
  430.       /* Get filename of X509 certificate */
  431.       LIST cert = new (FILE, path: certPath).list();
  432.       this.zip.addFile (dir: this.rootDir,
  433.          file: new (FILE, path: certPath + "/" + cert[0].basename ()));
  434.  
  435.       /* Write digital signature part rels */
  436.       STRING relsPath = xmlDsigPath + Xps.RELS_PATH;
  437.       FILE relsDir = new (FILE, path: relsPath);
  438.       relsDir.mkdirs ();
  439.  
  440.       writer = XmlWriterFactory.createFileWriter (
  441.                   filename: relsPath + "/signature.psdsxs.rels",
  442.                   indent: this.doIndent);
  443.       this.writePartStart (writer: writer,
  444.          localName: "Relationships", ns: Xps.RELS_NAMESPACE);
  445.       this.writePartRel (writer: writer,
  446.          target: Xps.DSIG_CERT_PATH + "/" + cert[0].basename (),
  447.              id: "RelsSignature0",
  448.            type: Xps.RELS_DIGITAL_SIGNATURE_CERTIFICATE_URI);
  449.       this.writePartEnd (writer: writer);
  450.       this.zip.addFile (dir: this.rootDir,
  451.          file: new (FILE, path: relsPath + "/signature.psdsxs.rels"));
  452.  
  453.       this.zip.addFile (dir: this.rootDir,
  454.          file: new (FILE, path: defPath + "/xml_1.xaml"));
  455.    }
  456.  
  457.    METHOD writeFixedPage (XpsPage page, INTEGER docNum, INTEGER pgNum) {
  458.       STRING pageUri = this.makePageUri (docNum: docNum, pgNum: pgNum);
  459.  
  460.       FILE dir = new (FILE, path: this.rootPath + pageUri).getParentFile ();
  461.       if (!dir.exists ())
  462.          dir.mkdirs ();
  463.  
  464.       this.pageWriter = XmlWriterFactory.createFileWriter (
  465.                            filename: this.rootPath + pageUri,
  466.                              indent: this.doIndent
  467.                            );
  468.  
  469.       this.writePartStart (writer: this.pageWriter,
  470.          localName: "FixedPage", ns: Xps.NAMESPACE);
  471.  
  472.       STRING w = page.width;
  473.       STRING h = page.height;
  474.       this.pageWriter.writeAttributeString (localName: "Width",  text: w);
  475.       this.pageWriter.writeAttributeString (localName: "Height", text: h);
  476.       this.pageWriter.writeAttributeString (prefix: "xml", localName: "lang",
  477.          text: "en-US"); // ns: Xps.XML_NAMESPACE
  478.  
  479.       this.addLayersContent (page: page, docNum: docNum, pgNum: pgNum);
  480.       this.writePartEnd (writer: this.pageWriter);
  481.    }
  482.  
  483.    METHOD writeEmptyPrintTicket () {
  484.       this.writePartStart (writer: this.ptWriter, prefix: "psf",
  485.          localName: "PrintTicket", ns: Xps.PRINT_TICKET_NAMESPACE);
  486.       this.ptWriter.writeAttributeString (localName: "version", text: "1");
  487.       this.writePartEnd (writer: this.ptWriter);
  488.    }
  489.  
  490.    METHOD addLayersContent (XpsPage page, INTEGER docNum, INTEGER pgNum) {
  491.       XIPIMAGE    img = page.xipage;
  492.       DOUBLE      fx  = page.fx;
  493.       DOUBLE      fy  = page.fy;
  494.       DOUBLE      bx  = page.contentBox_x;
  495.       DOUBLE      by  = page.contentBox_y;
  496.       DOUBLE      xpos, ypos, w, h;
  497.       STRING      brush, ext, str, stroke; // ="Stroke=\"#0000ff\""  // debugging;
  498.       STRING      xform_str, path_data_str, viewbox_str, viewport_str;
  499.       XIPCOLOR    color;
  500.       LIST        xform, coeffs, vport, viewport;
  501.       TRANSFORM2D matrix, rotmatrix;
  502.  
  503.       // Get orthogonal page rotation
  504.       INTEGER rot = img.getAttr (name:"_PDFrotate");
  505.       if (rot != 0) {
  506.         rotmatrix.rotate (angle: rot, fx: img.imageWidth / 2.0 * fx,
  507.            fy: img.imageHeight / 2.0 * fy);
  508.         }
  509.  
  510.       STRING  imgUri, glyphs, opacity_str = "0.0";
  511.       INTEGER i, ltype, txtfmt, r = 1;
  512.       for (i = 0; i < img.nlayers; i++) {
  513.          ltype = img.getMember (num: i, member: "layerType");
  514.  
  515.          if (ltype == XIP_JBIG2Dict || ltype == XIP_Thumbnail)
  516.             continue;
  517.  
  518.          xpos = bx + img.getMember (num: i, member: "xpos") * fx;
  519.          ypos = by + img.getMember (num: i, member: "ypos") * fy;
  520.          w    = img.getMember (num: i, member: "width")  * fx;
  521.          h    = img.getMember (num: i, member: "height") * fy;
  522.  
  523.          // Create viewbox value for current layer
  524.          viewbox_str = this.makeViewboxValue (img: img, layerNum: i);
  525.  
  526.          // Create matrix transform value
  527.          xform = img.getAttr (num:i, name:"_DIOMatrixTransform");
  528.          if (xform) {
  529.            matrix.setCoeffs (coeffs: xform);
  530.            coeffs = matrix.getCoeffs ();
  531.            coeffs[4] *= fx;
  532.            coeffs[5] *= fy;
  533.            }
  534.          else {
  535.            coeffs = (1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
  536.            }
  537.  
  538.          matrix.setCoeffs (coeffs: coeffs);
  539.          matrix.concatenate (other: rotmatrix);
  540.          xform_str = matrix.toString ();
  541.  
  542.          vport = img.getAttr (num:i, name:"_DIOOrigViewport");
  543.          if (vport) {
  544.             viewport = vport.Copy ();
  545.             viewport[0] *= fx;
  546.             viewport[1] *= fy;
  547.             viewport[2] *= fx;
  548.             viewport[3] *= fy;
  549.             }
  550.          else
  551.             viewport = (xpos, ypos, w, h);
  552.  
  553.          viewport_str  = this.makeViewportValue (win: viewport);
  554.          path_data_str = this.makePathDataValue (viewport: viewport);
  555.  
  556.          if (ltype == XIP_Contone || ltype == XIP_Binary) {
  557.             this.pageWriter.writeElementStart (localName: "Canvas");
  558.             this.pageWriter.writeElementStart (
  559.                localName: "Canvas.RenderTransform"
  560.                );
  561.             this.pageWriter.writeElementStart (localName: "MatrixTransform");
  562.             this.pageWriter.writeAttributeString (localName: "Matrix",
  563.                text: xform_str);
  564.             this.pageWriter.writeElementEnd ();
  565.             this.pageWriter.writeElementEnd ();
  566.  
  567.             this.pageWriter.writeElementStart (localName: "Path");
  568.             this.pageWriter.writeAttributeString (localName: "Data",
  569.                text: path_data_str);
  570.  
  571.             imgUri = page.getResource (resNum: r
  572.                         ).makeUri (docNum: docNum, pgNum: pgNum
  573.                         );
  574.  
  575.             this.pageWriter.writeElementStart (localName: "Path.Fill");
  576.             this.pageWriter.writeElementStart (localName: "ImageBrush");
  577.             this.pageWriter.writeAttributeString (localName: "ImageSource",
  578.                text: imgUri);
  579.             this.pageWriter.writeAttributeString (localName: "ViewboxUnits",                  text: "Absolute");
  580.             this.pageWriter.writeAttributeString (localName: "Viewbox",
  581.                text: viewbox_str);
  582.             this.pageWriter.writeAttributeString (localName: "ViewportUnits",
  583.                text: "Absolute");
  584.             this.pageWriter.writeAttributeString (localName: "Viewport",
  585.                text: viewport_str);
  586.             this.pageWriter.writeElementEnd ();
  587.             this.pageWriter.writeElementEnd ();
  588.             this.pageWriter.writeElementEnd ();
  589.             this.pageWriter.writeElementEnd ();
  590.             r++;
  591.             }
  592.          else if (ltype == XIP_Text) {
  593.             if ("$ESIPS_TEST_ENV") opacity_str = "1.0";
  594.             this.pageWriter.writeElementStart (localName: "Canvas");
  595.             this.pageWriter.writeAttributeString (localName: "Opacity",
  596.                text: opacity_str);
  597.             this.pageWriter.writeAttributeString (localName: "RenderTransform",
  598.                text: xform_str);
  599.  
  600.             glyphs = img.getAttr (name: "XpsGlyphs");
  601.             if (glyphs) {
  602.                // Append glyphs to FixedPage XML file
  603.                this.pageWriter.writeRaw (xmlstr: glyphs);
  604.                }
  605.             this.pageWriter.writeElementEnd ();
  606.  
  607.             txtfmt = img.getMember (num: i, member: "textformat");
  608.             if (txtfmt == XIP_XML_TEXT)
  609.                r++;
  610.             }
  611.          else if (ltype == XIP_ColorMask) {
  612.             color = img.getMember (num: i, member: "color");
  613.  
  614.             this.pageWriter.writeElementStart (localName: "Canvas");
  615.             this.pageWriter.writeElementStart (
  616.                localName: "Canvas.RenderTransform"
  617.                );
  618.             this.pageWriter.writeElementStart (localName: "MatrixTransform");
  619.             this.pageWriter.writeAttributeString (localName: "Matrix",
  620.                text: xform_str);
  621.             this.pageWriter.writeElementEnd ();
  622.             this.pageWriter.writeElementEnd ();
  623.  
  624.             this.pageWriter.writeElementStart (localName: "Path");
  625.             this.pageWriter.writeAttributeString (localName: "Fill",
  626.                text: this.color2hex (color: color));
  627.  
  628.             this.pageWriter.writeAttributeString (localName: "Data",
  629.                text: path_data_str);
  630.  
  631.             imgUri = page.getResource (resNum: r
  632.                         ).makeUri (docNum: docNum, pgNum: pgNum
  633.                         );
  634.  
  635.             this.pageWriter.writeElementStart (localName: "Path.OpacityMask");
  636.             this.pageWriter.writeElementStart (localName: "ImageBrush");
  637.             this.pageWriter.writeAttributeString (localName: "ImageSource",
  638.                text: imgUri);
  639.             this.pageWriter.writeAttributeString (localName: "ViewboxUnits",
  640.                text: "Absolute");
  641.             this.pageWriter.writeAttributeString (localName: "Viewbox",
  642.                text: viewbox_str);
  643.             this.pageWriter.writeAttributeString (localName: "ViewportUnits",
  644.                text: "Absolute");
  645.             this.pageWriter.writeAttributeString (localName: "Viewport",
  646.                text: viewport_str);
  647.             this.pageWriter.writeElementEnd ();
  648.             this.pageWriter.writeElementEnd ();
  649.             this.pageWriter.writeElementEnd ();
  650.             this.pageWriter.writeElementEnd ();
  651.             r++;
  652.             }
  653.          else if (ltype == XIP_ContoneMask) {
  654.             this.pageWriter.writeElementStart (localName: "Canvas");
  655.             this.pageWriter.writeAttributeString (
  656.                localName: "RenderOptions.EdgeMode",
  657.                text: "Aliased"
  658.                );
  659.  
  660.             this.pageWriter.writeElementStart (
  661.                localName: "Canvas.RenderTransform"
  662.                );
  663.             this.pageWriter.writeElementStart (localName: "MatrixTransform");
  664.             this.pageWriter.writeAttributeString (localName: "Matrix",
  665.                text: xform_str);
  666.             this.pageWriter.writeElementEnd ();
  667.             this.pageWriter.writeElementEnd ();
  668.  
  669.             this.pageWriter.writeElementStart (localName: "Path");
  670.             this.pageWriter.writeAttributeString (localName: "Data",
  671.                text: path_data_str);
  672.  
  673.             imgUri = page.getResource (resNum: r
  674.                         ).makeUri (docNum: docNum, pgNum: pgNum
  675.                         );
  676.  
  677.             this.pageWriter.writeElementStart (localName: "Path.OpacityMask");
  678.             this.pageWriter.writeElementStart (localName: "ImageBrush");
  679.             this.pageWriter.writeAttributeString (localName: "ImageSource",
  680.                text: imgUri);
  681.             this.pageWriter.writeAttributeString (localName: "ViewboxUnits",
  682.                text: "Absolute");
  683.             this.pageWriter.writeAttributeString (localName: "Viewbox",
  684.                text: viewbox_str);
  685.             this.pageWriter.writeAttributeString (localName: "ViewportUnits",
  686.                text: "Absolute");
  687.             this.pageWriter.writeAttributeString (localName: "Viewport",
  688.                text: viewport_str);
  689.             this.pageWriter.writeElementEnd ();
  690.             this.pageWriter.writeElementEnd ();
  691.  
  692.             i++; // Get the next Layer
  693.             xpos = bx + img.getMember (num: i, member: "xpos")   * fx;
  694.             ypos = by + img.getMember (num: i, member: "ypos")   * fy;
  695.             w    = img.getMember (num: i, member: "width")  * fx;
  696.             h    = img.getMember (num: i, member: "height") * fy;
  697.  
  698.             // Create viewbox value for next layer
  699.             viewbox_str = this.makeViewboxValue (img: img, layerNum: i);
  700.  
  701.             vport = img.getAttr (num:i, name:"_DIOOrigViewport");
  702.             if (vport) {
  703.                viewport = vport.Copy ();
  704.                viewport[0] *= fx;
  705.                viewport[1] *= fy;
  706.                viewport[2] *= fx;
  707.                viewport[3] *= fy;
  708.                }
  709.             else
  710.                viewport = (xpos, ypos, w, h);
  711.  
  712.             viewport_str = this.makeViewportValue (win: viewport);
  713.  
  714.             r++; // Get next resource
  715.             imgUri = page.getResource (resNum: r
  716.                         ).makeUri (docNum: docNum, pgNum: pgNum
  717.                         );
  718.  
  719.             this.pageWriter.writeElementStart (localName: "Path.Fill");
  720.             this.pageWriter.writeElementStart (localName: "ImageBrush");
  721.             this.pageWriter.writeAttributeString (localName: "ImageSource",
  722.                text: imgUri);
  723.             this.pageWriter.writeAttributeString (localName: "ViewboxUnits",
  724.                text: "Absolute");
  725.             this.pageWriter.writeAttributeString (localName: "Viewbox",
  726.                text: viewbox_str);
  727.             this.pageWriter.writeAttributeString (localName: "ViewportUnits",
  728.                text: "Absolute");
  729.             this.pageWriter.writeAttributeString (localName: "Viewport",
  730.                text: viewport_str);
  731.             this.pageWriter.writeElementEnd ();
  732.             this.pageWriter.writeElementEnd ();
  733.             this.pageWriter.writeElementEnd ();
  734.             this.pageWriter.writeElementEnd ();
  735.             r++;
  736.             }
  737.          }
  738.    }
  739.  
  740.    METHOD mapHex (INTEGER num)
  741.      RETURNS (STRING hex) {
  742.       STRING  h  = "0123456789ABCDEF";
  743.       INTEGER v1 = num / 16;
  744.       INTEGER v2 = num - v1 * 16;
  745.  
  746.       hex = h.index (val: v1) + h.index (val: v2);
  747.    }
  748.  
  749.    METHOD color2hex (XIPCOLOR color)
  750.      RETURNS (STRING hex) {
  751.       if (!color) {
  752.          hex = "#000000";
  753.          }
  754.       else {
  755.          if ((color.photometry == XIP_GRAY_COLOR) ||
  756.              (color.photometry == XIP_SGRAY_COLOR)) {
  757.             hex = "#" + this.mapHex (num: color.c[0])
  758.                       + this.mapHex (num: color.c[0])
  759.                       + this.mapHex (num: color.c[0]);
  760.             }
  761.          else {
  762.             hex = "#" + this.mapHex (num: color.c[0])
  763.                       + this.mapHex (num: color.c[1])
  764.                       + this.mapHex (num: color.c[2]);
  765.             }
  766.          }
  767.    }
  768.  
  769.    METHOD makeViewboxValue (XIPIMAGE img, INTEGER layerNum)
  770.      RETURNS (STRING value) {
  771.       DOUBLE  xres, yres;
  772.  
  773.       DOUBLE pix = img.getMember (num:layerNum, member:"pixels");
  774.       DOUBLE scl = img.getMember (num:layerNum, member:"scanlines");
  775.  
  776.       xres = img.getMember (num:layerNum, member:"xres");
  777.       yres = img.getMember (num:layerNum, member:"yres");
  778.  
  779.       if (xres == 0.0)
  780.          xres = 96.0;
  781.  
  782.       if (yres == 0.0)
  783.          yres = 96.0;
  784.  
  785.       DOUBLE w = pix * 96.0 / xres;
  786.       DOUBLE h = scl * 96.0 / yres;
  787.  
  788.       value = "0,0," + w + "," + h;
  789.    }
  790.  
  791.    METHOD makeViewportValue (LIST win) RETURNS (STRING value)
  792.    {
  793.       value = win[0] + "," + win[1] + "," + win[2] + "," + win[3];
  794.    }
  795.  
  796.    METHOD makePathDataValue (LIST viewport) RETURNS (STRING value)
  797.    {
  798.       DOUBLE x, y, w, h;
  799.       x = viewport[0];
  800.       y = viewport[1];
  801.       w = viewport[2];
  802.       h = viewport[3];
  803.  
  804.       value = "M " + x     + "," + y     + " L "
  805.                    + (x+w) + "," + y     + " "
  806.                    + (x+w) + "," + (y+h) + " "
  807.                    + x     + "," + (y+h) + " Z";
  808.    }
  809.  
  810.    METHOD makeDocUri (INTEGER docNum)
  811.      RETURNS (STRING uri) {
  812.       uri = Xps.DOCS_PATH + "/" + docNum + "/FixedDocument.fdoc";
  813.    }
  814.  
  815.    METHOD makeDocRelsUri (INTEGER docNum)
  816.      RETURNS (STRING uri) {
  817.       uri = Xps.DOCS_PATH + "/" + docNum +
  818.               Xps.RELS_PATH + "/FixedDocument.fdoc.rels";
  819.    }
  820.  
  821.    METHOD makePageUri (INTEGER docNum, INTEGER pgNum)
  822.      RETURNS (STRING uri) {
  823.       uri = Xps.DOCS_PATH + "/" + docNum +
  824.                Xps.PAGES_PATH + "/" + pgNum + ".fpage";
  825.    }
  826.  
  827.    METHOD makePageRelsUri (INTEGER docNum, INTEGER pgNum)
  828.      RETURNS (STRING uri) {
  829.       uri = Xps.DOCS_PATH + "/" + docNum + Xps.PAGES_PATH +
  830.                Xps.RELS_PATH + "/" + pgNum + ".fpage.rels";
  831.    }
  832. }
  833.  
  834. /****************************************************************************/
  835. /*
  836. ** This class defines the no package interleaving order (NONE) for the major
  837. ** parts of an XPS package. In this strategy, the order of the package parts
  838. ** is determined by the packaging system, i.e. the ZIP class.
  839. */
  840. /* @write Writes an XPS package with no interleaving order. */
  841. /* @writeContentTypes Writes content types of an XPS package. */
  842. /* @writeFixedDocument Writes FixedDocument part of a FixedDocumentSequence. */
  843. /* @writeFixedDocumentSequence Writes FixedDocumentSequence part of an XPS package. */
  844. /* @writeFixedPageContent Writes relationships and resources of a FixedPage part. */
  845. /* @writePackageRels Writes package relationships part of an XPS package. */
  846. /****************************************************************************/
  847. CLASS XpsNoInterleavingStrategy EXTENDS XpsBasePackagingStrategy {
  848.    METHOD New () {
  849.       this.name = "XpsNoInterleavingStrategy";
  850.    }
  851.  
  852.    METHOD write (XpsPackage pkg, STRING filename, XpsOptions options) {
  853.       this.open (filename: filename, options: options);
  854.  
  855.       this.writeContentTypes ();
  856.       this.writePackageRels (pkg: pkg, filename: filename);
  857.       this.writeCoreProperties (props: pkg.props);
  858.       this.writeFixedDocumentSequence (seq: pkg.seq);
  859.  
  860.       XpsDocument doc;
  861.       XpsPage     page;
  862.       INTEGER     i, j;
  863.       for (i = 1; i <= pkg.seq.getDocumentCount (); i++) {
  864.          doc = pkg.seq.getDocument (docNum: i);
  865.          this.writeFixedDocument (doc: doc, docNum: i);
  866.  
  867.          for (j = 1; j <= doc.getPageCount (); j++) {
  868.             page = doc.getPage (pgNum: j);
  869.             this.writeFixedPage (page: page, docNum: i, pgNum: j);
  870.             this.writeFixedPageContent (page: page, docNum: i, pgNum: j);
  871.             }
  872.          }
  873.  
  874.       this.zip.addFiles (dir: this.rootDir, recurse: TRUE);
  875.  
  876.       if (this.signPackage)
  877.          this.writeDigitalSignature (pkg: pkg);
  878.  
  879.       this.close ();
  880.    }
  881.  
  882.    METHOD writeContentTypes () {
  883.       this.typesWriter = XmlWriterFactory.createFileWriter (
  884.                             filename: this.rootPath + Xps.CONTENT_TYPES_PATH,
  885.                               indent: this.doIndent
  886.                             );
  887.  
  888.       this.writePartStart (writer: this.typesWriter, localName: "Types",
  889.          ns: Xps.CONTENT_TYPES_NAMESPACE);
  890.  
  891.       this.writeExtType (ext: "rels",  type: Xps.RELS_TYPE);
  892.       this.writeExtType (ext: "fdseq", type: Xps.FDSEQ_TYPE);
  893.       this.writeExtType (ext: "fdoc",  type: Xps.FDOC_TYPE);
  894.       this.writeExtType (ext: "fpage", type: Xps.FPAGE_TYPE);
  895.       this.writePartType (partName: Xps.CORE_PROPS_PATH,
  896.          type: Xps.CORE_XML_TYPE);
  897.  
  898.       this.writeExtType (ext: "jpg", type: Xps.JPEG_TYPE);
  899.       this.writeExtType (ext: "png", type: Xps.PNG_TYPE);
  900.       this.writeExtType (ext: "tif", type: Xps.TIFF_TYPE);
  901.  
  902.       this.writeExtType (ext: "ttf",   type: Xps.TTF_TYPE);
  903.       this.writeExtType (ext: "odttf", type: Xps.ODTTF_TYPE);
  904.  
  905.       if (this.signPackage) {
  906.          this.writeExtType (ext: "cer",
  907.             type: Xps.DIGITAL_SIGNATURE_CERT_TYPE);
  908.          this.writeExtType (ext: "psdsor",
  909.             type: Xps.DIGITAL_SIGNATURE_ORIGIN_TYPE);
  910.          this.writeExtType (ext: "psdsxs",
  911.             type: Xps.DIGITAL_SIGNATURE_XML_TYPE);
  912.          this.writeExtType (ext: "xaml",
  913.             type: Xps.XML_TYPE);
  914.          }
  915.  
  916.       this.writePartEnd (writer: this.typesWriter);
  917.    }
  918.  
  919.    METHOD writePackageRels (XpsPackage pkg, STRING filename) {
  920.       FILE dir = new (FILE, path: this.rootPath + Xps.RELS_PATH);
  921.       dir.mkdir ();
  922.  
  923.       this.relsWriter = XmlWriterFactory.createFileWriter (
  924.                            filename: dir.getPath () + "/.rels",
  925.                              indent: this.doIndent
  926.                            );
  927.  
  928.       this.writePartStart (writer: this.relsWriter,
  929.          localName: "Relationships", ns: Xps.RELS_NAMESPACE);
  930.  
  931.       INTEGER relsCount = 0;
  932.       this.writePartRel (writer: this.relsWriter, target: Xps.SEQ_PATH,
  933.          id: "R" + relsCount, type: Xps.RELS_FIXED_REP_URI);
  934.       relsCount++;
  935.  
  936.       this.writePartRel (writer: this.relsWriter, target: Xps.CORE_PROPS_PATH,
  937.          id: "R" + relsCount, type: Xps.RELS_CORE_PROPS_URI);
  938.       relsCount++;
  939.  
  940.       XpsThumbnail thumb = pkg.getThumbnail ();
  941.       STRING       thumbUri;
  942.  
  943.       if (thumb) {
  944.          thumbUri = thumb.makeUri ();
  945.          }
  946.       else {
  947.          XpsDocument doc = pkg.getDocument (docNum: 1);
  948.          if (doc) {
  949.             CLASSREF    cr   = REFLECTION.findClass (name: "XpsThumbnail");
  950.             XpsPage     page = doc.getPage (pgNum: 1);
  951.             XpsResource res;
  952.             INTEGER     i;
  953.             for (i = page.getResourceCount (); i > 0; i--) {
  954.                res = page.getResource (resNum: i);
  955.                if (cr.isInstance (obj: res)) {
  956.                   thumb = res;
  957.                   break;
  958.                   }
  959.                }
  960.  
  961.             if (thumb)
  962.                thumbUri = thumb.makeUri (docNum: 1, pgNum: 1);
  963.             }
  964.          }
  965.  
  966.       if (thumbUri) {
  967.          this.writePartRel (writer: this.relsWriter, target: thumbUri,
  968.             id: "R"+ relsCount, type: Xps.RELS_THUMBNAIL_URI);
  969.          relsCount++;
  970.          }
  971.  
  972.       if (this.signPackage) {
  973.          this.writePartRel (writer: this.relsWriter,
  974.             target: Xps.DSIG_ORIGIN,
  975.             id: "R"+ relsCount, type: Xps.RELS_DIGITAL_SIGNATURE_ORIGIN_URI);
  976.          }
  977.  
  978.       this.writePartEnd (writer: this.relsWriter);
  979.    }
  980.  
  981.    METHOD writeFixedDocumentSequence (XpsSequence seq) {
  982.       /* Write Relationships file for FixedDocumentSequence part */
  983.       STRING relsUri = Xps.RELS_PATH + Xps.SEQ_PATH + ".rels";
  984.  
  985.       new (FILE, path: this.rootPath + relsUri).getParentFile ().mkdirs ();
  986.  
  987.       this.seqRelsWriter = XmlWriterFactory.createFileWriter (
  988.                               filename: this.rootPath + relsUri,
  989.                                 indent: this.doIndent
  990.                               );
  991.  
  992.       this.writePartStart (writer: this.seqRelsWriter,
  993.          localName: "Relationships", ns: Xps.RELS_NAMESPACE);
  994.       this.writePartEnd (writer: this.seqRelsWriter);
  995.  
  996.       /* Write FixedDocumentSequence part */
  997.       this.seqWriter = XmlWriterFactory.createFileWriter (
  998.                           filename: this.rootPath + Xps.SEQ_PATH,
  999.                             indent: this.doIndent
  1000.                           );
  1001.  
  1002.       this.writePartStart (writer: this.seqWriter,
  1003.          localName: "FixedDocumentSequence", ns: Xps.NAMESPACE);
  1004.  
  1005.       INTEGER i;
  1006.       for (i = 1; i <= seq.getDocumentCount (); i++)
  1007.          this.writeDocumentReference (docNum: i);
  1008.  
  1009.       this.writePartEnd (writer: this.seqWriter);
  1010.    }
  1011.  
  1012.    METHOD writeFixedDocument (XpsDocument doc, INTEGER docNum) {
  1013.       /* Write Relationships file for FixedDocument part */
  1014.       STRING relsUri = this.makeDocRelsUri (docNum: docNum);
  1015.  
  1016.       new (FILE, path: this.rootPath + relsUri).getParentFile ().mkdirs ();
  1017.  
  1018.       this.docRelsWriter = XmlWriterFactory.createFileWriter (
  1019.                               filename: this.rootPath + relsUri,
  1020.                                 indent: this.doIndent
  1021.                               );
  1022.  
  1023.       this.writePartStart (writer: this.docRelsWriter,
  1024.          localName: "Relationships", ns: Xps.RELS_NAMESPACE);
  1025.  
  1026.       if (this.signPackage) {
  1027.          this.writePartRel (writer: this.docRelsWriter,
  1028.             target: "/xmls/xml_1.xaml", id: "R0",
  1029.             type: Xps.SIGNATURE_DEFS_NAMESPACE);
  1030.          }
  1031.  
  1032.       this.writePartEnd (writer: this.docRelsWriter);
  1033.  
  1034.       /* Write FixedDocument part */
  1035.       STRING docUri = this.makeDocUri (docNum: docNum);
  1036.  
  1037.       new (FILE, path: this.rootPath + docUri).getParentFile ().mkdirs ();
  1038.  
  1039.       this.docWriter = XmlWriterFactory.createFileWriter (
  1040.                           filename: this.rootPath + docUri,
  1041.                             indent: this.doIndent
  1042.                           );
  1043.  
  1044.       this.writePartStart (writer: this.docWriter,
  1045.          localName: "FixedDocument", ns: Xps.NAMESPACE);
  1046.  
  1047.       INTEGER i;
  1048.       for (i = 1; i <= doc.getPageCount (); i++)
  1049.          this.writePageContent (docNum: docNum, pgNum: i);
  1050.  
  1051.       this.writePartEnd (writer: this.docWriter);
  1052.    }
  1053.  
  1054.    METHOD writeFixedPageContent (XpsPage page, INTEGER docNum, INTEGER pgNum) {
  1055.       STRING relsUri = this.makePageRelsUri (docNum: docNum, pgNum: pgNum);
  1056.  
  1057.       new (FILE, path: this.rootPath + relsUri).getParentFile ().mkdirs ();
  1058.  
  1059.       this.pageRelsWriter = XmlWriterFactory.createFileWriter (
  1060.                                filename: this.rootPath + relsUri,
  1061.                                  indent: this.doIndent
  1062.                                );
  1063.  
  1064.       this.writePartStart (writer: this.pageRelsWriter,
  1065.          localName: "Relationships", ns: Xps.RELS_NAMESPACE);
  1066.  
  1067.       XpsResource res;
  1068.       STRING      targetUri;
  1069.       INTEGER     i;
  1070.       for (i = 1; i <= page.getResourceCount (); i++) {
  1071.          res = page.getResource (resNum: i);
  1072.  
  1073.          targetUri = res.makeUri (docNum: docNum, pgNum: pgNum);
  1074.  
  1075.          this.writePartRel (writer: this.pageRelsWriter, target: targetUri,
  1076.             id: "R" + (i - 1), type: res.getTypeUri ());
  1077.  
  1078.          res.write (filename: this.rootPath + targetUri);
  1079.          }
  1080.  
  1081.       this.writePartEnd (writer: this.pageRelsWriter);
  1082.    }
  1083. }
  1084.  
  1085. /****************************************************************************/
  1086. /*
  1087. ** This class defines the RESOURCES FIRST package interleaving order for the
  1088. ** major parts of an XPS package. In this strategy, the order of the package
  1089. ** parts is: resources, page, document, and document sequence.
  1090. */
  1091. /* @write Writes an XPS package in Resources First interleaving order. */
  1092. /****************************************************************************/
  1093. CLASS XpsResourcesFirstStrategy EXTENDS XpsBasePackagingStrategy {
  1094.    METHOD New () {
  1095.       this.name = "XpsResourcesFirstStrategy";
  1096.    }
  1097.  
  1098.    METHOD write (XpsPackage pkg, STRING filename, XpsOptions options) {
  1099.       SetStatus (op: "stop", msg: "NotSupportedException");
  1100.    }
  1101. }
  1102.  
  1103. /****************************************************************************/
  1104. /*
  1105. ** This class defines the RESOURCES LAST package interleaving order for the
  1106. ** major parts of an XPS package. In this strategy, the order of the package
  1107. ** parts is: document sequence, document, page, and resources.
  1108. */
  1109. /* @write Writes an XPS package in Resources Last interleaving order. */
  1110. /****************************************************************************/
  1111. CLASS XpsResourcesLastStrategy EXTENDS XpsBasePackagingStrategy {
  1112.    METHOD New () {
  1113.       this.name = "XpsResourcesLastStrategy";
  1114.    }
  1115.  
  1116.    METHOD write (XpsPackage pkg, STRING filename, XpsOptions options) {
  1117.       this.open (filename: filename, options: options);
  1118.  
  1119.       STRING typesPath = this.rootPath + Xps.CONTENT_TYPES_PATH;
  1120.       new (FILE, path: typesPath).mkdir ();
  1121.  
  1122.       /* Build content_types piece for _rels/.rels */
  1123.       this.typesWriter =
  1124.          XmlWriterFactory.createStringWriter (indent: this.doIndent);
  1125.       this.writePartStart (writer: this.typesWriter, localName: "Types",
  1126.          ns: Xps.CONTENT_TYPES_NAMESPACE);
  1127.       this.writePartType (partName: Xps.RELS_PATH + "/.rels",
  1128.          type: Xps.RELS_TYPE);
  1129.  
  1130.       FILE typesFile = new (FILE, path: typesPath +
  1131.                           "/[" + this.typesCount + "].piece");
  1132.       this.typesWriter.toString (
  1133.          ).trim (
  1134.          ).Write (filename: typesFile.getPath (), value: 1
  1135.          );
  1136.       this.typesWriter.reset ();
  1137.       this.zip.addFile (dir: this.rootDir, file: typesFile);
  1138.       this.typesCount++;
  1139.  
  1140.       /* Create _rels/.rels directory */
  1141.       STRING relsPath = this.rootPath + Xps.RELS_PATH + "/.rels";
  1142.       new (FILE, path: relsPath).mkdirs ();
  1143.  
  1144.       /* Write _rels/.rels piece for core properties */
  1145.       this.relsWriter =
  1146.          XmlWriterFactory.createStringWriter (indent: this.doIndent);
  1147.       this.writePartStart (writer: this.relsWriter, localName: "Relationships",
  1148.          ns: Xps.RELS_NAMESPACE);
  1149.       this.writePartRel (writer: this.relsWriter, target: Xps.CORE_PROPS_PATH,
  1150.          id: "R0", type: Xps.RELS_CORE_PROPS_URI);
  1151.  
  1152.       FILE relsFile = new (FILE, path: relsPath + "/[0].piece");
  1153.       this.relsWriter.toString (
  1154.          ).trim (
  1155.          ).Write (filename: relsFile.getPath (), value: 1
  1156.          );
  1157.       this.relsWriter.reset ();
  1158.       this.zip.addFile (dir: this.rootDir, file: relsFile);
  1159.  
  1160.       /* Write content_types piece for core properties */
  1161.       typesFile = new (FILE, path: typesPath +
  1162.                      "/[" + this.typesCount + "].piece");
  1163.  
  1164.       this.writePartType (partName: Xps.CORE_PROPS_PATH,
  1165.          type: Xps.CORE_XML_TYPE);
  1166.       this.typesWriter.toString (
  1167.          ).trim (
  1168.          ).Write (filename: typesFile.getPath (), value: 1
  1169.          );
  1170.       this.typesWriter.reset ();
  1171.  
  1172.       this.zip.addFile (dir: this.rootDir, file: typesFile);
  1173.       this.typesCount++;
  1174.  
  1175.       /* Write core properties */
  1176.       FILE propsFile = new (FILE, path: this.rootPath + Xps.CORE_PROPS_PATH);
  1177.       this.propsWriter = XmlWriterFactory.createFileWriter (
  1178.                             filename: propsFile.getPath (),
  1179.                               indent: this.doIndent
  1180.                             );
  1181.       this.writeCoreProperties (props: pkg.props);
  1182.       this.zip.addFile (dir: this.rootDir, file: propsFile);
  1183.  
  1184.       /* Write content_types piece for fdseq.rels */
  1185.       typesFile = new (FILE, path: typesPath +
  1186.                      "/[" + this.typesCount + "].piece");
  1187.  
  1188.       this.writePartType (partName: Xps.SEQ_RELS_PATH, type: Xps.RELS_TYPE);
  1189.       this.typesWriter.toString (
  1190.          ).trim (
  1191.          ).Write (filename: typesFile.getPath (), value: 1
  1192.          );
  1193.       this.typesWriter.reset ();
  1194.  
  1195.       this.zip.addFile (dir: this.rootDir, file: typesFile);
  1196.       this.typesCount++;
  1197.  
  1198.       /* Write fdseq.rels piece for shared print ticket */
  1199.       STRING seqRelsPath = this.rootPath + Xps.SEQ_RELS_PATH;
  1200.       new (FILE, path: seqRelsPath).mkdir ();
  1201.  
  1202.       relsFile = new (FILE, path: seqRelsPath + "/[0].piece");
  1203.  
  1204.       this.seqRelsWriter =
  1205.          XmlWriterFactory.createStringWriter (indent: this.doIndent);
  1206.       this.writePartStart (writer: this.seqRelsWriter,
  1207.          localName: "Relationships", ns: Xps.RELS_NAMESPACE);
  1208.       this.writePartRel (writer: this.seqRelsWriter, target: Xps.JOB_PT_PATH,
  1209.          id: "R0", type: Xps.PRINT_TICKET_URI);
  1210.       this.seqRelsWriter.toString (
  1211.          ).trim (
  1212.          ).Write (filename: relsFile.getPath (), value: 1
  1213.          );
  1214.       this.seqRelsWriter.reset ();
  1215.       this.zip.addFile (dir: this.rootDir, file: relsFile);
  1216.  
  1217.       /* Write content_types piece for shared print ticket */
  1218.       typesFile = new (FILE, path: typesPath +
  1219.                      "/[" + this.typesCount + "].piece");
  1220.  
  1221.       this.writePartType (partName: Xps.JOB_PT_PATH, type: Xps.PT_TYPE);
  1222.       this.typesWriter.toString (
  1223.          ).trim (
  1224.          ).Write (filename: typesFile.getPath (), value: 1
  1225.          );
  1226.       this.typesWriter.reset ();
  1227.       this.zip.addFile (dir: this.rootDir, file: typesFile);
  1228.       this.typesCount++;
  1229.  
  1230.       /* Write shared print ticket */
  1231.       new (FILE, path: this.rootPath + Xps.METADATA_PATH).mkdir ();
  1232.  
  1233.       STRING ptPath = this.rootPath + Xps.JOB_PT_PATH;
  1234.       FILE ptFile = new (FILE, path: ptPath);
  1235.       this.ptWriter = XmlWriterFactory.createFileWriter (
  1236.                          filename: ptPath,
  1237.                            indent: this.doIndent
  1238.                          );
  1239.       this.writeEmptyPrintTicket ();
  1240.       this.zip.addFile (dir: this.rootDir, file: ptFile);
  1241.  
  1242.       /* Write fdseq.rels last piece */
  1243.       relsFile = new (FILE, path: seqRelsPath + "/[1].last.piece");
  1244.       this.writePartEnd (writer: this.seqRelsWriter);
  1245.       this.seqRelsWriter.toString (
  1246.          ).trim (
  1247.          ).Write (filename: relsFile.getPath (), value: 1
  1248.          );
  1249.       this.zip.addFile (dir: this.rootDir, file: relsFile);
  1250.  
  1251.       /* Write _rels/.rels piece for fdseq */
  1252.       relsFile = new (FILE, path: relsPath + "/[1].piece");
  1253.  
  1254.       this.writePartRel (writer: this.relsWriter, target: Xps.SEQ_PATH,
  1255.          id: "R1", type: Xps.RELS_FIXED_REP_URI);
  1256.       this.relsWriter.toString (
  1257.          ).trim (
  1258.          ).Write (filename: relsFile.getPath (), value: 1
  1259.          );
  1260.       this.relsWriter.reset ();
  1261.       this.zip.addFile (dir: this.rootDir, file: relsFile);
  1262.  
  1263.       /* Write content_types piece for fdseq */
  1264.       typesFile = new (FILE, path: typesPath +
  1265.                      "/[" + this.typesCount + "].piece");
  1266.  
  1267.       this.writePartType (partName: Xps.SEQ_PATH, type: Xps.FDSEQ_TYPE);
  1268.       this.typesWriter.toString (
  1269.          ).trim (
  1270.          ).Write (filename: typesFile.getPath (), value: 1
  1271.          );
  1272.       this.typesWriter.reset ();
  1273.       this.zip.addFile (dir: this.rootDir, file: typesFile);
  1274.       this.typesCount++;
  1275.  
  1276.       STRING seqPath = this.rootPath + Xps.SEQ_PATH;
  1277.       new (FILE, path: seqPath).mkdir ();
  1278.  
  1279.       this.seqWriter =
  1280.          XmlWriterFactory.createStringWriter (indent: this.doIndent);
  1281.       this.writePartStart (writer: this.seqWriter,
  1282.          localName: "FixedDocumentSequence", ns: Xps.NAMESPACE);
  1283.  
  1284.       XpsDocument doc;
  1285.       XpsPage     page;
  1286.       XpsResource res;
  1287.       FILE        seqFile, docFile, docRelsFile;
  1288.       FILE        pageFile, pageRelsFile, resFile;
  1289.       LIST        resMap, resList;
  1290.       STRING      docUri, docRelsUri, pageUri, pageRelsUri, resUri;
  1291.       STRING      docPath, pagesPath, pagesRelsPath;
  1292.       INTEGER     i, j, k, pageRelsCount;
  1293.       for (i = 1; i <= pkg.seq.getDocumentCount (); i++) {
  1294.          docPath = Xps.DOCS_PATH + "/" + i;
  1295.  
  1296.          docUri = this.makeDocUri (docNum: i);
  1297.          new (FILE, path: this.rootPath + docUri).mkdirs ();
  1298.  
  1299.          new (FILE, path: this.rootPath + docUri).getParentFile ().mkdirs ();
  1300.  
  1301.          /* Write fdseq piece for fdoc */
  1302.          seqFile = new (FILE, path: this.rootPath + Xps.SEQ_PATH +
  1303.                       "/[" + (i-1) + "].piece");
  1304.          this.writeDocumentReference (docNum: i);
  1305.          this.seqWriter.toString (
  1306.             ).trim (
  1307.             ).Write (filename: seqFile.getPath (), value: 1
  1308.             );
  1309.          this.seqWriter.reset ();
  1310.          this.zip.addFile (dir: this.rootDir, file: seqFile);
  1311.  
  1312.          this.docRelsWriter =
  1313.             XmlWriterFactory.createStringWriter (indent: this.doIndent);
  1314.          this.writePartStart (writer: this.docRelsWriter,
  1315.             localName: "Relationships", ns: Xps.RELS_NAMESPACE);
  1316.  
  1317.          /* Write content_types piece for fpage & fpage.rels */
  1318.          typesFile = new (FILE, path: typesPath +
  1319.                         "/[" + this.typesCount + "].piece");
  1320.  
  1321.          docRelsUri = this.makeDocRelsUri (docNum: i);
  1322.          new (FILE, path: this.rootPath + docRelsUri).mkdirs ();
  1323.          this.writePartType (partName: docRelsUri, type: Xps.RELS_TYPE);
  1324.          this.typesWriter.toString (
  1325.             ).trim (
  1326.             ).Write (filename: typesFile.getPath (), value: 1
  1327.             );
  1328.          this.typesWriter.reset ();
  1329.          this.zip.addFile (dir: this.rootDir, file: typesFile);
  1330.          this.typesCount++;
  1331.  
  1332.          /* Write fdoc.rels piece for print ticket */
  1333.          docRelsFile = new (FILE, path: this.rootPath + docRelsUri +
  1334.             "/[0].piece");
  1335.  
  1336.          this.writePartRel (writer: this.docRelsWriter,
  1337.             target: Xps.JOB_PT_PATH, id: "R0", type: Xps.PRINT_TICKET_URI);
  1338.          this.docRelsWriter.toString (
  1339.             ).trim (
  1340.             ).Write (filename: docRelsFile.getPath (), value: 1
  1341.             );
  1342.          this.docRelsWriter.reset ();
  1343.          this.zip.addFile (dir: this.rootDir, file: docRelsFile);
  1344.  
  1345.          docRelsFile = new (FILE, path: this.rootPath + docRelsUri +
  1346.             "/[1].last.piece");
  1347.  
  1348.          this.writePartEnd (writer: this.docRelsWriter);
  1349.          this.docRelsWriter.toString (
  1350.             ).trim (
  1351.             ).Write (filename: docRelsFile.getPath (), value: 1
  1352.             );
  1353.          this.zip.addFile (dir: this.rootDir, file: docRelsFile);
  1354.  
  1355.          /* Write content_types piece for fdoc */
  1356.          typesFile = new (FILE, path: typesPath +
  1357.                         "/[" + this.typesCount + "].piece");
  1358.  
  1359.          this.writePartType (partName: docUri, type: Xps.FDOC_TYPE);
  1360.          this.typesWriter.toString (
  1361.             ).trim (
  1362.             ).Write (filename: typesFile.getPath (), value: 1
  1363.             );
  1364.          this.typesWriter.reset ();
  1365.          this.zip.addFile (dir: this.rootDir, file: typesFile);
  1366.          this.typesCount++;
  1367.  
  1368.          pagesPath = docPath + Xps.PAGES_PATH;
  1369.          pagesRelsPath = pagesPath + Xps.RELS_PATH;
  1370.          new (FILE, path: this.rootPath + pagesRelsPath).mkdirs ();
  1371.  
  1372.          this.docWriter =
  1373.             XmlWriterFactory.createStringWriter (indent: this.doIndent);
  1374.          this.writePartStart (writer: this.docWriter,
  1375.             localName: "FixedDocument", ns: Xps.NAMESPACE);
  1376.  
  1377.          doc = pkg.seq.documents[i-1];
  1378.          for (j = 1; j <= doc.getPageCount (); j++) {
  1379.             page = doc.getPage (pgNum: i);
  1380.  
  1381.             docFile = new (FILE, path: this.rootPath + docUri +
  1382.                          "/[" + (j-1) + "].piece");
  1383.             this.writePageContent (docNum: i, pgNum: j);
  1384.             this.docWriter.toString (
  1385.                ).trim (
  1386.                ).Write (filename: docFile.getPath (), value: 1
  1387.                );
  1388.             this.docWriter.reset ();
  1389.  
  1390.             this.zip.addFile (dir: this.rootDir, file: docFile);
  1391.  
  1392.             /* Write content_types piece for fpage & fpage.rels */
  1393.             typesFile = new (FILE, path: typesPath +
  1394.                            "/[" + this.typesCount + "].piece");
  1395.  
  1396.             pageUri = this.makePageUri (docNum: i, pgNum: j);
  1397.             this.writePartType (partName: pageUri, type: Xps.FPAGE_TYPE);
  1398.             pageRelsUri = this.makePageRelsUri (docNum: i, pgNum: j);
  1399.             new (FILE, path: this.rootPath + pageRelsUri).mkdir ();
  1400.             this.writePartType (partName: pageRelsUri, type: Xps.RELS_TYPE);
  1401.             this.typesWriter.toString (
  1402.                ).trim (
  1403.                ).Write (filename: typesFile.getPath (), value: 1
  1404.                );
  1405.             this.typesWriter.reset ();
  1406.             this.zip.addFile (dir: this.rootDir, file: typesFile);
  1407.             this.typesCount++;
  1408.  
  1409.             this.pageRelsWriter =
  1410.                XmlWriterFactory.createStringWriter (indent: this.doIndent);
  1411.             this.writePartStart (writer: this.pageRelsWriter,
  1412.                localName: "Relationships", ns: Xps.RELS_NAMESPACE);
  1413.  
  1414.             resList.clear ();
  1415.             pageRelsCount = 0;
  1416.             for (k = 1; k <= page.getResourceCount (); k++) {
  1417.                res = page.getResource (resNum: k);
  1418.  
  1419.                /* Check if resource has already been added to archive */
  1420.                /* Currently, only fonts can be a shared resource      */
  1421.                if (res.getId ().indexOf (match: "Font") == 0 &&
  1422.                    resMap.ref (name: res.getId ())) {
  1423.                   resList.insert (entry: resList.length (), obj: res);
  1424.                   }
  1425.                else {
  1426.                   resUri = res.makeUri (docNum: i, pgNum: j);
  1427.  
  1428.                   /* Write fpage.rels piece for resource */
  1429.                   pageRelsFile = new (FILE, path: this.rootPath + pageRelsUri +
  1430.                      "/[" + pageRelsCount + "].piece");
  1431.  
  1432.                   this.writePartRel (writer: this.pageRelsWriter,
  1433.                      target: resUri, id: "R" + pageRelsCount,
  1434.                      type: res.getTypeUri ());
  1435.                   this.pageRelsWriter.toString (
  1436.                      ).trim (
  1437.                      ).Write (filename: pageRelsFile.getPath (), value: 1
  1438.                      );
  1439.                   this.pageRelsWriter.reset ();
  1440.                   this.zip.addFile (dir: this.rootDir, file: pageRelsFile);
  1441.                   pageRelsCount++;
  1442.  
  1443.                   /* Write content_types piece for resource */
  1444.                   typesFile = new (FILE, path: typesPath +
  1445.                                  "/[" + this.typesCount + "].piece");
  1446.  
  1447.                   this.writePartType (partName: resUri,
  1448.                      type: res.getMimeType ());
  1449.                   this.typesWriter.toString (
  1450.                      ).trim (
  1451.                      ).Write (filename: typesFile.getPath (), value: 1
  1452.                      );
  1453.                   this.typesWriter.reset ();
  1454.                   this.zip.addFile (dir: this.rootDir, file: typesFile);
  1455.                   this.typesCount++;
  1456.  
  1457.                   /* Write resource */
  1458.                   resFile = new (FILE, path: this.rootPath + resUri);
  1459.                   res.write (filename: this.rootPath + resUri);
  1460.                   this.zip.addFile (dir: this.rootDir, file: resFile);
  1461.  
  1462.                   resMap.insert (name: res.getId (), obj: res);
  1463.                   }
  1464.                }
  1465.  
  1466.             /* Write fpage.rels piece for print ticket */
  1467.             pageRelsFile = new (FILE, path: this.rootPath + pageRelsUri +
  1468.                "/[" + pageRelsCount + "].piece");
  1469.  
  1470.             this.writePartRel (writer: this.pageRelsWriter,
  1471.                target: Xps.JOB_PT_PATH, id: "R" + pageRelsCount,
  1472.                type: Xps.PRINT_TICKET_URI);
  1473.             this.pageRelsWriter.toString (
  1474.                ).trim (
  1475.                ).Write (filename: pageRelsFile.getPath (), value: 1
  1476.                );
  1477.             this.pageRelsWriter.reset ();
  1478.             this.zip.addFile (dir: this.rootDir, file: pageRelsFile);
  1479.             pageRelsCount++;
  1480.  
  1481.             /* Write fpage.rels piece for resources already in archive */
  1482.             if (resList.length ()) {
  1483.                pageRelsFile = new (FILE, path: this.rootPath + pageRelsUri +
  1484.                   "/[" + pageRelsCount + "].piece");
  1485.  
  1486.                foreach (resList: r) {
  1487.                   resUri = r.makeUri (docNum: i, pgNum: j);
  1488.  
  1489.                   this.writePartRel (writer: this.pageRelsWriter,
  1490.                      target: resUri, id: "R" + pageRelsCount,
  1491.                       type: r.getTypeUri ());
  1492.                   this.pageRelsWriter.toString (
  1493.                      ).trim (
  1494.                      ).Write (filename: pageRelsFile.getPath (), value: 1,
  1495.                         mode: "a"
  1496.                      );
  1497.                   }
  1498.                this.pageRelsWriter.reset ();
  1499.                this.zip.addFile (dir: this.rootDir, file: pageRelsFile);
  1500.                pageRelsCount++;
  1501.                }
  1502.  
  1503.                pageRelsFile = new (FILE, path: this.rootPath + pageRelsUri +
  1504.                   "/[" + pageRelsCount + "].last.piece");
  1505.  
  1506.                this.writePartEnd (writer: this.pageRelsWriter);
  1507.                this.pageRelsWriter.toString (
  1508.                   ).trim (
  1509.                   ).Write (filename: pageRelsFile.getPath (), value: 1
  1510.                   ); 
  1511.                this.zip.addFile (dir: this.rootDir, file: pageRelsFile);
  1512.  
  1513.             this.pageWriter = XmlWriterFactory.createFileWriter (
  1514.                                  filename: this.rootPath + pageUri,
  1515.                                    indent: this.doIndent
  1516.                                  );
  1517.             this.writeFixedPage (page: page, docNum: i, pgNum: j);
  1518.  
  1519.             pageFile = new (FILE, path: this.rootPath + pageUri);
  1520.             this.zip.addFile (dir: this.rootDir, file: pageFile);
  1521.             }
  1522.  
  1523.          docFile = new (FILE, path: this.rootPath + docUri +
  1524.                       "/[" + doc.getPageCount () + "].last.piece");
  1525.          this.writePartEnd (writer: this.docWriter);
  1526.          this.docWriter.toString (
  1527.             ).trim (
  1528.             ).Write (filename: docFile.getPath (), value: 1
  1529.             );
  1530.  
  1531.          this.zip.addFile (dir: this.rootDir, file: docFile);
  1532.          }
  1533.  
  1534.       /* Write fdseq last piece */
  1535.       seqFile = new (FILE, path: this.rootPath + Xps.SEQ_PATH +
  1536.                    "/[" + pkg.seq.getDocumentCount () + "].last.piece");
  1537.       this.writePartEnd (writer: this.seqWriter);
  1538.       this.seqWriter.toString (
  1539.          ).trim (
  1540.          ).Write (filename: seqFile.getPath (), value: 1
  1541.          );
  1542.       this.zip.addFile (dir: this.rootDir, file: seqFile);
  1543.  
  1544.       /* Write _rels/.rels last piece */
  1545.       relsFile = new (FILE, path: relsPath + "/[2].last.piece");
  1546.       this.writePartEnd (writer: this.relsWriter);
  1547.       this.relsWriter.toString (
  1548.          ).trim (
  1549.          ).Write (filename: relsFile.getPath (), value: 1
  1550.          );
  1551.       this.zip.addFile (dir: this.rootDir, file: relsFile);
  1552.  
  1553.       /* Write content_types last piece */
  1554.       typesFile = new (FILE, path: typesPath +
  1555.                      "/[" + this.typesCount + "].last.piece");
  1556.       this.writePartEnd (writer: this.typesWriter);
  1557.       this.typesWriter.toString (
  1558.          ).trim (
  1559.          ).Write (filename: typesFile.getPath (), value: 1
  1560.          );
  1561.       this.zip.addFile (dir: this.rootDir, file: typesFile);
  1562.  
  1563.       this.close ();
  1564.    }
  1565. }
  1566.  
  1567. /****************************************************************************/
  1568. /*
  1569. ** This class defines the IMAGES LAST package interleaving order for the
  1570. ** major parts of an XPS package. In this strategy, the order of the package
  1571. ** parts is: resources (excluding images), page, document, document sequence,
  1572. ** and images.
  1573. */
  1574. /* @write Writes an XPS package in Images Last interleaving order. */
  1575. /****************************************************************************/
  1576. CLASS XpsImagesLastStrategy EXTENDS XpsBasePackagingStrategy {
  1577.    METHOD New () {
  1578.       this.name = "XpsImagesLastStrategy";
  1579.    }
  1580.  
  1581.    METHOD write (XpsPackage pkg, STRING filename, XpsOptions options) {
  1582.       SetStatus (op: "stop", msg: "NotSupportedException");
  1583.    }
  1584. }
  1585.  
  1586. /****************************************************************************/
  1587. /*
  1588. ** This class provides the means to create an instance of a strategy for
  1589. ** packaging the data in an XPS package. The packaging strategy instance
  1590. ** implements the physical format in which the parts of an XPS package are
  1591. ** written to file.
  1592. */
  1593. /* @getStrategy Returns an instance of the requested packaging strategy. */
  1594. /****************************************************************************/
  1595. CLASS XpsPackagingStrategyFactory {
  1596.    METHOD getStrategy (STRING name)
  1597.      RETURNS (XpsBasePackagingStrategy s) {
  1598.       s = REFLECTION.findClass (name: name).newInstance ();
  1599.    }
  1600. }
  1601.